// LoadBriefingState.cpp: implementation of the LoadBriefingState class.
//
//////////////////////////////////////////////////////////////////////

#include "LoadBriefingState.h"
#include "ViewBriefingState.h"

#include <plib/ul.h>
#include <plib/pu.h>
#include <plib/puAux.h>
#include <plib/fnt.h>

#include "BackGroundImage.h"
#include "ImageButton.h"
#include "VideoImage.h"
#include "ProgressBar.h"
#include "Keyboard.h"
#include "Joystick.h"
#include "Mouse.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

LoadBriefingState::LoadBriefingState()
{
this->oldState = NULL;
shouldDeleteNextState = FALSE;
this->nextState = NULL;
this->load("");
}

LoadBriefingState::LoadBriefingState(State* oldState)
{
this->oldState = oldState;
shouldDeleteNextState = FALSE;
this->nextState = NULL;
this->load("");
}

LoadBriefingState::~LoadBriefingState()
{
delete backgroundImage;
delete backButton;
delete backDisabledButton;
delete cancelButton;
delete cancelDisabledButton;
delete ms;
delete kb;
}

void LoadBriefingState::load(const char* filename)
{
	
#ifdef WIN32
// Must be initialized but only here works well!!!
// Use a different critical section for each state where needed
//InitializeCriticalSection(&criticalSection);
#endif
	
progress = 0.0f;

int h = (float)glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ;
int w = (float)glutGet ( (GLenum) GLUT_WINDOW_WIDTH  ) ;
    
this->backgroundImage = new BackGroundImage("./LoadBriefingState.bmp");

                                      
backButton = new ImageButton("./backNormal.bmp",
                             "./backFocused.bmp",
                             "./backClicked.bmp",
                             eAlphaKey_RED,
                             0.24f,0.01f,0.15f,0.1f);
backDisabledButton = new ImageButton("./backDisabled.bmp",
                             "./backDisabled.bmp",
                             "./backDisabled.bmp",
                             eAlphaKey_RED,
                             0.24f,0.01f,0.15f,0.1f);
cancelButton = new ImageButton("./cancelNormal.bmp",
                             "./cancelFocused.bmp",
                             "./cancelClicked.bmp",
                             eAlphaKey_RED,
                             0.57f,0.01f,0.16f,0.1f);
cancelDisabledButton = new ImageButton("./cancelDisabled.bmp",
                             "./cancelDisabled.bmp",
                             "./cancelDisabled.bmp",
                             eAlphaKey_RED,
                             0.57f,0.01f,0.16f,0.1f);

loadButton = new ImageButton("./loadNormal.bmp",
                             "./loadFocused.bmp",
                             "./loadClicked.bmp",
                             eAlphaKey_RED,
                             0.40f,0.10f,0.20f,0.10f);

loadingImage = new VideoImage("./Loading1.bmp",
                             "./Loading2.bmp",
                             "./Loading3.bmp",
                             eAlphaKey_RED,
                             0.30f,0.15f,0.40f,0.2f,0.4f);

cancelingImage = new VideoImage("./Canceling1.bmp",
                             "./Canceling2.bmp",
                             "./Canceling3.bmp",
                             eAlphaKey_RED,
                             0.30f,0.15f,0.40f,0.2f,0.4f);

scenarioProgressBar = new ProgressBar(0.6f,0.62f,0.25f,0.04f,8,PB_COLOR_SUNBURST);
mapProgressBar      = new ProgressBar(0.6f,0.51f,0.25f,0.04f,8,PB_COLOR_SUNBURST);
textureProgressBar  = new ProgressBar(0.6f,0.4f, 0.25f,0.04f,8,PB_COLOR_SUNBURST);

createPUI(w,h);

/* Other stuff */
this->kb = new Keyboard();
this->ms = new Mouse();
                             
backButtonEnabled = true;
cancelButtonEnabled = false;

nextState = this;
innerState = NEW_SCENARIO_SELECTION; 
lc = FALSE;

// function used to communucation between threads
this->info.completed = false;
this->info.mapProgress = 0.0f;
this->info.objectsProgress = 0.0f;
this->info.scenarioProgress = 0.0f;
this->info.texturesProgress = 0.0f;
this->info.canceled = false;
this->info.doneCanceling = false;
}

void LoadBriefingState::createPUI(int w, int h)
{
/* FONT creation */
fnt = new fntTexFont( "./DEFAULT.txf" );
font = new puFont(PUFONT_HELVETICA_18);
tex_font = new puFont( fnt, 18.0f, 0 );

/* PUI default settings */
//puSetDefaultFonts        ( *tex_font, *font );
puSetDefaultStyle        ( PUSTYLE_SMALL_SHADED ) ;
puSetDefaultColourScheme ( COLOR_ICE ) ;

progress_group = new puGroup(0,0);

sprintf(scenario_progress_label,"SCENARIO CREATION PROGRESS");
scenario_progress_text = new puText(0.21f * w, 0.62f * h);
scenario_progress_text -> setLabel(scenario_progress_label);
scenario_progress_text -> setColor(PUCOL_LABEL,COLOR_SUNBURST);
scenario_progress_text -> setLabelFont(*font);

sprintf(map_progress_label,"MAP CREATION PROGRESS");
map_progress_text = new puText(0.21f * w, 0.51f * h);
map_progress_text -> setLabel(map_progress_label);
map_progress_text -> setColor(PUCOL_LABEL,COLOR_SUNBURST);
map_progress_text -> setLabelFont(*font);

sprintf(texture_progress_label,"TEXTURE CREATION PROGRESS");
texture_progress_text = new puText(0.21f * w, 0.40f * h);
texture_progress_text -> setLabel(texture_progress_label);
texture_progress_text -> setColor(PUCOL_LABEL,COLOR_SUNBURST);
texture_progress_text -> setLabelFont(*font);

progress_group->close();
progress_group->hide();

browse_group = new puGroup(0,0);

/* PUI widgets' settings */
sprintf(info_label,INFO_STRING3);
info_text = new puText(0.11f * w, 0.68f * h);
info_text -> setLabel(info_label);
info_text -> setColor(PUCOL_LABEL,COLOR_SUNBURST);

sprintf(brf_file,"Choose a scenario (.BRF) file");
brfFileText = new puFrame (0.11f * w, 0.58f * h, 0.8f * w, 0.62f * h);
brfFileText -> setLegend(brf_file);
brfFileText -> setColor(PUCOL_LEGEND,COLOR_WHITE);

brfFileBrowse = new puOneShot(0.81f * w,0.58f * h,"Browse");
brfFileBrowse -> setCallback(browse_brf);
brfFileBrowse -> setUserData(this);
brfFileBrowse -> setColor(PUCOL_BACKGROUND,COLOR_RED);
brfFileBrowse -> setColor(PUCOL_FOREGROUND,COLOR_SUNBURST);
brfFileBrowse -> setColor(PUCOL_HIGHLIGHT,COLOR_SUNBURST);
brfFileBrowse -> setColor(PUCOL_LABEL, COLOR_WHITE);
brfFileBrowse -> setColor(PUCOL_LEGEND, COLOR_WHITE);

browse_group -> close();
}

void LoadBriefingState::reset()
{
//this->nextState = this;

backButtonEnabled = true;
cancelButtonEnabled = false;

innerState = NEW_SCENARIO_SELECTION; 

cancelButton->reset();
cancelDisabledButton->reset();
backButton->reset();
backDisabledButton->reset();
loadButton->reset();

this->cancelButtonEnabled = FALSE;
this->backButtonEnabled = TRUE;

lc = FALSE;

browse_group->hide();
progress_group->hide();

info.canceled = FALSE;
info.completed = FALSE;
info.old_s = this;
info.doneCanceling = FALSE;
}

void LoadBriefingState::display(void)
{
// background image, always displayed
backgroundImage->display();

// those buttons should always be displayed
if (cancelButtonEnabled) cancelButton->display();
else cancelDisabledButton->display();
if (backButtonEnabled) backButton->display();
else backDisabledButton->display();

   
if(innerState == NEW_SCENARIO_SELECTION)
         {
         // show PUI widgets	 
         }
else if(innerState == NEW_SCENARIO_SELECTED)
		{
         // show load buttons
         loadButton->display();	     
		}
else if(innerState == NEW_SCENARIO_LOADING)
		{
         // show loading image
         loadingImage->display();
         
         float sp;
         float mp;
         float tp;
         
         // copy the values to leave the critical section quickly

		 sp = info.scenarioProgress;
		 mp = info.mapProgress;
	     tp = info.texturesProgress;
		 lc = info.completed;
			
         // show progress bars
         scenarioProgressBar->display(sp);
         mapProgressBar->display(mp);
         textureProgressBar->display(tp);
         }
else if(innerState == NEW_SCENARIO_CANCELING)
         {
         bool dc = false;
         cancelingImage->display();

             dc = info.doneCanceling;

         if(dc) 
             {
             innerState = NEW_SCENARIO_SELECTION;
             info.doneCanceling = false;
             info.canceled = false;
             info.completed = false;
             backButtonEnabled = true;
             cancelButtonEnabled = false;
			 browse_group -> reveal();
             }
         }

// Display PUI  
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GREATER,0.1f);
puDisplay();
}

void LoadBriefingState::resize(int w, int h)
{

}

void LoadBriefingState::keyUp(unsigned char key, int x, int y)
{
kb->read(key,GLUT_UP,x,y);
}

void LoadBriefingState::keyDown(unsigned char key, int x, int y)
{
kb->read(key,GLUT_DOWN,x,y);
}

void LoadBriefingState::specialUp(int key, int x, int y)
{
kb->read(key,GLUT_UP,x,y);
}

void LoadBriefingState::specialDown(int key, int x, int y)
{
kb->read(key,GLUT_DOWN,x,y);
}


void LoadBriefingState::motion(int newx, int newy)
{
puMouse(newx,newy); 
}

void LoadBriefingState::passive(int newx, int newy)
{
if(backButtonEnabled) backButton->mouse(-1,-1,newx,newy);
else backDisabledButton->mouse(-1,-1,newx,newy);
if (cancelButtonEnabled) cancelButton->mouse(-1,-1,newx,newy);
else cancelDisabledButton->mouse(-1,-1,newx,newy);
loadButton->mouse(-1,-1,newx,newy);
puMouse(-1,-1,newx,newy);
}

void LoadBriefingState::mouse(int button, int state, int mouseX, int mouseY)
{
puMouse(button,state,mouseX,mouseY);
  
if(innerState == NEW_SCENARIO_SELECTED)
{

if(loadButton->mouse(button,state,mouseX,mouseY))
     {
     backButtonEnabled = false;
     cancelButtonEnabled = true;
     innerState = NEW_SCENARIO_LOADING;     
     progress_group -> reveal();
	 browse_group -> hide();
     //info.cs = &criticalSection;
	 info.old_s = this;
	 info.cnt = ssgGetCurrentContext();

	 strcpy(info.snr_filename,this->snr_file);
	 printf("FILE SNR: %s\n",info.snr_filename);

	 strcpy(info.wrd_filename,this->wrd_file);
	 printf("FILE WRD: %s\n",info.wrd_filename);

	 strcpy(info.wrdmap_filename,this->wrdmap_file);
	 printf("FILE WRD: %s\n",info.wrdmap_filename);

	 info.h = (float)glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ;
	 info.w = (float)glutGet ( (GLenum) GLUT_WINDOW_WIDTH  ) ;

	 loadTextures(&info);
	 info.loadingType = BRIEF;
	// ViewBriefingState *vbs = new ViewBriefingState(this,&info);
     // start thread
     /*hThread = (HANDLE) _beginthreadex(NULL,0,loadBriefing,&info,0,(unsigned int *)&dwThreadId);
     // Check the return value for success. 
	 if (hThread == NULL)
		{
        exit(0);
	    }*/
     }
}     

if(backButtonEnabled) 
     { 
     if(backButton->mouse(button,state,mouseX,mouseY)) 
           this->nextState = this->oldState;
     }
if(cancelButtonEnabled) 
     { 
     if(cancelButton->mouse(button,state,mouseX,mouseY))
           {
           // cancel operation
           backButtonEnabled = false;
           cancelButtonEnabled = false;
           innerState = NEW_SCENARIO_CANCELING;
           progress_group -> hide();
           // safely stop thread!!!!
           doCritical(info.canceled = true, &cs);
		   }
     }
}

State* LoadBriefingState::idle(void)
{
//printf("LoadBriefingState\n");
if(kb->isPressed(27)) exit(0);
//if(kb->isPressed(GLUT_KEY_LEFT))       info.scenarioProgress -= 0.01f;
//if(kb->isPressed(GLUT_KEY_RIGHT))      info.scenarioProgress += 0.01f;
//if(kb->isPressed(GLUT_KEY_UP))         info.mapProgress -= 0.01f;
//if(kb->isPressed(GLUT_KEY_DOWN))       info.mapProgress += 0.01f;
//if(kb->isPressed(GLUT_KEY_PAGE_UP))    info.texturesProgress -= 0.01f;
//if(kb->isPressed(GLUT_KEY_PAGE_DOWN))  info.texturesProgress += 0.01f;

if(lc) { this->nextState = info.s; ViewBriefingState *tmps = (ViewBriefingState*) info.s; tmps->bindTextures(); tmps->createStates();}

if(shouldDeleteNextState) this->deleteNextState();

if(nextState == this) {return nextState;}
else {State* tmpState = nextState; this->reset(); return tmpState;}
}

void LoadBriefingState::loadTextures(LoadingInfo *li)
{
ssgTexture *t1 = new ssgTexture(map_file);//"./snow1.bmp");//map_file);//
ssgTexture *t2 = new ssgTexture(map_file);//"./snow1.bmp");

li->textures[GRASS0_TEXTURE] = t1->getHandle();
li->textures[STONES0_TEXTURE] = t2->getHandle();

readAndLoadLandTextures(li);

li->texturesProgress = 1.0f;
}

void LoadBriefingState::readAndLoadLandTextures(LoadingInfo *li)
{

FILE* f;
ssgTexture *t;
char line[1024];
char path[2050];
bool go = FALSE;
int jj = 0;
int i = 0;

if( (f = fopen(TEXTURE_TYPE_FILE_NAME0,"r")) != NULL)
	{
	while( fscanf(f,"%s",line) != EOF )
		{
		adjustFileName(line);
		ulMakePath(path,TEXTURE_PATH,line);
		t = new ssgTexture(path);		
		li->textures[COUNTRYSIDE_TEXTURES+jj] = t->getHandle();
		jj+=1;
		}
	li->landTextures = jj;
	fclose(f);
	}
else
	{
	printf("Cannot open textures file %s\n",TEXTURE_TYPE_FILE_NAME0);
	}
}

void LoadBriefingState::reload()
{
this->browse_group->reveal();
this->shouldDeleteNextState = TRUE;
}

void LoadBriefingState::reopen()
{
backButtonEnabled = true;
cancelButtonEnabled = false;

nextState = this;
innerState = NEW_SCENARIO_SELECTION; 

cancelButton->reset();
cancelDisabledButton->reset();
backButton->reset();
backDisabledButton->reset();
loadButton->reset();

this->cancelButtonEnabled = FALSE;
this->backButtonEnabled = TRUE;

lc = FALSE;

browse_group->reveal();
}

void LoadBriefingState::deleteNextState()
{
delete this->nextState;
this->nextState = this;
this->shouldDeleteNextState = FALSE;
}

unsigned int LoadBriefingState::loadBriefing(void *lpParam)
{
// cast to the struct used for intercommunication
LoadingInfo* li = (LoadingInfo*)lpParam;
li->cnt->makeCurrent();
//printf("In loadNewScenario %d\n",&criticalSection);
// create in this separate thread the new state
// The li structure will be modified concurrently, using critical regions (I hope!)
//ViewBriefingState *vbs = new ViewBriefingState(li->old_s,li);
// li.state should contain the pointer to the ViewBriefingState;
doCritical(li->completed = true, li->cs);

return 1;
}

void LoadBriefingState::pick_brf ( puObject * p)
{
  LoadBriefingState* lbs;
  lbs = (LoadBriefingState*) p->getUserData();

  p -> getValue(lbs->brf_file);

  // is really a .DEM file ???
  char ext[4];
  int i = 0;
  bool go = true;

  // default string

  while( go ) 
  {
  if( *(lbs->brf_file + i)  == '.')
	{
	ext[0] = *(lbs->brf_file+i + 1);
	ext[1] = *(lbs->brf_file+i + 2);
	ext[2] = *(lbs->brf_file+i + 3);
	ext[3] = '\0';
	go = false;
	}
  else if( *(lbs->brf_file + i) == '\0')
	{
	go = false;
	}
  else
	{
	  i++;
	}
  }

  //printf("file: %s ext: %s",nss->dem_file,ext);
FILE *f;
char string[1024];

  if( (strcmp(ext,"BRF\0") == 0) || (strcmp(ext,"brf\0") == 0) )
	{
    lbs->innerState = NEW_SCENARIO_SELECTED;
	// load file names from .brf file!!!


	if((f = fopen(lbs->brf_file,"r")) != NULL)
		{
		fgets(string,1024,f);

		fgets(lbs->snr_file,1024,f);
		adjustFileName(lbs->snr_file);

		fgets(string,1024,f);

		fgets(lbs->wrd_file,1024,f);
		adjustFileName(lbs->wrd_file);

		fgets(lbs->wrdmap_file,1024,f);
		adjustFileName(lbs->wrdmap_file);

		fclose(f);
		}
	else
		{
		printf("Cannot open .brf file %s for loading...\n",lbs->brf_file);
		}
	}
  else
	{
	strcpy(lbs->brf_file,"Not a .BRF file... Choose Another one!!!\0");
	}
  
  if((f = fopen(lbs->snr_file,"r")) != NULL)
	{
	fgets(string,1024,f);
	fgets(string,1024,f);
	fgets(string,1024,f);
	fgets(lbs->map_file,1024,f);
	adjustFileName(lbs->map_file);
	fclose(f);
	}
  else
	{
	printf("Cannot open .snr file %s for loading...\n",lbs->snr_file);
	}

  puDeleteObject ( p ) ;
  p = 0 ;
}

void LoadBriefingState::browse_brf ( puObject * p)
{
  int h = (float)glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ;
  int w = (float)glutGet ( (GLenum) GLUT_WINDOW_WIDTH  ) ;

  puOneShot *pos = (puOneShot*)p;
  LoadBriefingState* nss = (LoadBriefingState*) pos->getUserData();
  puaFileSelector *pfs =  new puaFileSelector ( 0.11f * w, 0.21f * h, 0.77f * w, 0.5f * h, 2, START_DIRECTORY , "Select the .BRF file" ) ;
  pfs -> setCallback ( pick_brf ) ;
  pfs -> setUserData( nss );
  pfs -> setChildColour( PUCLASS_OBJECT, PUCOL_FOREGROUND, COLOR_SUNBURST );
  pfs -> setChildColour( PUCLASS_OBJECT, PUCOL_BACKGROUND, COLOR_RED );
  pfs -> setChildColour( PUCLASS_OBJECT, PUCOL_HIGHLIGHT,  COLOR_SUNBURST );
  pfs -> setChildColour( PUCLASS_INPUT, PUCOL_HIGHLIGHT,   COLOR_ICE );
  pfs -> setChildColour( PUCLASS_INPUT, PUCOL_FOREGROUND,  COLOR_WHITE );
  pfs -> setChildColour( PUCLASS_INPUT, PUCOL_BACKGROUND,  COLOR_ICE );
  pfs -> setChildColour( PUCLASS_OBJECT, PUCOL_LABEL    ,  COLOR_WHITE );
  pfs -> setChildColour( PUCLASS_ONESHOT, PUCOL_LEGEND  ,  COLOR_WHITE );
  pfs -> setChildColour( PUCLASS_ONESHOT, PUCOL_LABEL    , COLOR_WHITE );
}

